Skip to content

Fix jump-to-date being off by one day in non-UTC timezones#14816

Open
fethij wants to merge 1 commit into
signalapp:mainfrom
fethij:fix-jump-to-date-off-by-one
Open

Fix jump-to-date being off by one day in non-UTC timezones#14816
fethij wants to merge 1 commit into
signalapp:mainfrom
fethij:fix-jump-to-date-off-by-one

Conversation

@fethij
Copy link
Copy Markdown

@fethij fethij commented May 28, 2026

Resolves #14342.

Problem

In the conversation search "jump to date" picker, the selectable dates are one day ahead of the day they actually refer to (e.g. a message sent on 2025-06-20 only becomes selectable under 2025-06-21).

MaterialDatePicker works entirely in UTC: the selection, the calendar constraints, and the DateValidator callbacks are all UTC-midnight timestamps for the displayed calendar day. The picker is set up correctly (LocalDateTime.now().atMidnight().atUTC()), but both places that read a value back reinterpret that UTC-midnight instant in the local zone:

Instant.ofEpochMilli(timestamp).atZone(ZoneId.systemDefault()).toLocalDate()
  • JumpToDateValidator.normalizeToLocalMidnight() — decides which calendar cells are selectable
  • the date pickers positive-button handler in ConversationFragment — computes where to jump

For any negative UTC offset, UTC midnight of calendar day D falls on the previous evening locally, so toLocalDate() returns D-1. The validator therefore enables day D for messages that actually live on local day D-1 (the "one day ahead" symptom), and the jump target is shifted by a day too.

The database keys message days by local midnight (MessageTable.messageExistsOnDays: DATE_SENT >= startOfDay AND DATE_SENT < startOfDay + 86400000), so the correct mapping is: read the calendar day from the picker in UTC, then re-anchor that day to local midnight.

Fix

Use ZoneOffset.UTC when extracting the LocalDate from the picker timestamp in both read-back paths, keeping atStartOfDay(zoneId) to anchor at local midnight. Both sites must change together so the selectable day and the jump target stay consistent.

Testing

Added a regression test to JumpToDateValidatorTest for a negative-offset zone (America/New_York): a picker selection of June 15 (UTC midnight) must map to New Yorks June 15, not June 14.

Verified locally against the pinned toolchain (:Signal-Android:testPlayProdDebugUnitTest --tests "*JumpToDateValidatorTest"):

  • Before the fix: 10 tests completed, 1 failed (the new test fails — expected to be true).
  • After the fix: tests="10" skipped="0" failures="0" errors="0".

@fethij fethij force-pushed the fix-jump-to-date-off-by-one branch from 1bb6adc to 742dc06 Compare May 28, 2026 22:00
Copy link
Copy Markdown
Contributor

@mtang-signal mtang-signal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, I'm fine with this change, but I don't think a lot of these comments are necessary and can be removed.

@fethij fethij force-pushed the fix-jump-to-date-off-by-one branch from 742dc06 to 24f07c1 Compare June 1, 2026 16:22
MaterialDatePicker reports the selected day, the calendar constraints, and
the validator callbacks in terms of UTC midnight. When reading those values
back, both JumpToDateValidator.normalizeToLocalMidnight() and the date
picker's positive-button handler converted the UTC-midnight instant using
the local zone:

    Instant.ofEpochMilli(timestamp).atZone(ZoneId.systemDefault()).toLocalDate()

For any negative UTC offset, the UTC-midnight instant of calendar day D
falls on the previous evening locally, so toLocalDate() yields D-1. As a
result a message sent on local day D became selectable under picker day
D+1 (the reported "selectable dates are one day ahead" symptom), and the
positive-button handler shifted the jump target by a day as well.

Read the calendar day in UTC (matching how MaterialDatePicker emits it),
then re-anchor to local midnight, which is how message days are keyed in
the database (messageExistsOnDays). Add a regression test exercising a
negative-offset zone (America/New_York); it fails before this change and
passes after.
@fethij fethij force-pushed the fix-jump-to-date-off-by-one branch from 24f07c1 to f9294d6 Compare June 1, 2026 16:24
@fethij
Copy link
Copy Markdown
Author

fethij commented Jun 1, 2026

In general, I'm fine with this change, but I don't think a lot of these comments are necessary and can be removed.

Done!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Jump to date is off by one day

2 participants